#ifndef MODULES_CORE_TASK_H_
#define MODULES_CORE_TASK_H_

#include "../common.h"
template<typename T>
class ProxyFunction {
private:
	TaskFunction<T> fn;
	TaskCtx<T> *ctx;
public:
	ProxyFunction(TaskFunction<T> fn, TaskCtx<T> *ctx) :
					fn(fn), ctx(ctx) {
	}
	void call() {
		this->fn(this->ctx);
	}

	void del() {
		if (ctx != nullptr) {
			ctx->decAndGc();
		}
		fn = NULL;
		ctx = NULL;
		delete this;
	}
};
static std::vector<RandomRatio<uint8_t>> _coreCpuRatios = { { 1, 10 }, { 0, 90 }, };
static std::atomic<uint32_t> _taskSize(0);
static bool _shutdown(false);
static uint32_t _taskNameCount = 0;
static uint16_t _taskPriority = 100;
const uint16_t _StackDepth = 1024 * 4;

class Task {
public:
	static void deleteCurrTask();
	static long getTaskSize();
	static void delay(uint64_t milliseconds);
	static bool isShutdown();
	static void shutdown();

	/***
	 * @param fn 最后一行代码必须要删除任务 Task::deleteTask();
	 * @param arg  //变量生命周期必须是全局或 new 出来在heap里
	 * @param ctx taskSize 执行执行完后-1 为0时自动删除 ctx
	 * */
	template<typename T>
	static void run(TaskFunction<T> fn, TaskCtx<T> *ctx) {
		const char *name = "task:" + _taskNameCount++;
		//防止不停生成任务造成内存不足
		while (_taskSize >= 100) {
			delay(2000);
		}

		_taskSize++;
		_taskPriority++;
		_taskPriority = _taskPriority > 6000 ? 100 : _taskPriority;

		//TaskHandle_t taskHandle;
		ProxyFunction<T> *_arg = new ProxyFunction<T>(fn, ctx);

		TaskFunction_t proxyFn = [](void *_arg) -> void {
			_taskSize--;
			ProxyFunction<T> *_proxy = (ProxyFunction<T>*) _arg;
			try {
				_proxy->call();
			} catch (std::exception &e) {
				Serial.print("task run error:");
				Serial.println(e.what());
			} catch (const char *msg) {
				Serial.print("task run error:");
				Serial.println(msg);
			} catch (...) {
				Serial.println("task run unknown error");
			}
			_proxy->del();
			//Serial.print("delete task end : stack ");
			//Serial.println(uxTaskGetStackHighWaterMark(xTaskGetCurrentTaskHandle()));
			_proxy = NULL;
			Task::deleteCurrTask();
		};
		//应用层。。。不同线程会出错。。。
		int coreCpu = 1;
		if (ctx == nullptr) {
			coreCpu = 1;
		} else if (ctx->cpu > -1) {
			coreCpu = ctx->cpu;
		} else {
			coreCpu = random(_coreCpuRatios);
		}
		//xTaskCreateUniversal(proxyFn, name, _StackDepth, _arg, _taskPriority, &taskHandle, coreCpu);
		xTaskCreateUniversal(proxyFn, name, _StackDepth, _arg, _taskPriority, NULL, coreCpu);
	}

	template<typename T>
	static void run(TaskFunction<T> fn) {
		TaskCtx<T> *ctx = nullptr;
		run(fn, ctx);
	}
};

#endif /* MODULES_CORE_TASK_H_ */
